# theme.py
"""
Register, compile, and use Lib-Ray Wizard themes.

Note that the test below assumes that the 'default.zip' zipped theme is identical (up-to-date) to the 'default' theme directory. You'll only get a pass if this is true.

>>> import theme
>>> import os
>>> os.chdir(theme.THEME_DIR)
>>> d = theme.theme_dir('default')
>>> z = theme.theme_zip('default.zip')
>>> index1 = d.load('index.html')
>>> index2 = z.load('index.html')
>>> index1 == index2
True
>>>
"""

# Standard library imports
import os, zipfile, StringIO

try:
    import ConfigParser as configparser
except:
    import configparser

# Dependencies
from simpletal import simpleTAL as TAL

# local
# from config import THEME_DIR
THEME_DIR = '../../lib-ray-video-tools-testfixtures/themes'


# Module variable holds all available themes by name:
themes = {}

class theme_zip(zipfile.ZipFile):
    """
    Access and load theme elements from zip archive.
    """
    def __init__(self, themepath):
        zipfile.ZipFile.__init__(self, themepath)
        self.name = [n for n in self.namelist() if n[-1]=='/'][0][:-1]      
        
    def load(self, filename):
        """
        Load a file from the archive as text.
        """
        try:
            data = self.open(self.name + '/' + filename).read()
        except KeyError:
            data = None
        return data

class theme_dir(object):
    """
    Access and load theme elements from a directory.
    """
    def __init__(self, themepath):
        self.path = themepath
        self.name = os.path.basename(self.path)
        if not os.path.isdir(self.path):
            raise IOError("No such theme file")
        
    def load(self, filename):
        """
        Load file as text.
        """
        try:
            data = open(os.path.join(self.path, filename), 'r').read()
        except IOError:
            data = None
        return data
        

theme_options = ['CHAPTERS_PER_PAGE', 'CHAPTERS_ROWS', 'TITLE_IN_INDEX']
        
class Theme(object):
    """
    Represents a theme for Lib-Ray Wizard.
    """
    def __init__(self, path, preload=False):
        if os.path.isdir(path):
            self.source = theme_dir(path)
        else:
            self.source = theme_zip(path)
        self.name = self.source.name
        self.description = self.source.load('description.txt')
        self.errors = {}
        self._get_configuration()
        if preload:
            self.load()
            
    def _get_configuration(self):
        """
        Extract settings from theme.
        """
        self.options = {}
        try:
            cfp = configparser.ConfigParser(allow_no_value=True)
            cfp.readfp(StringIO.StringIO(self.source.load('theme.conf')))
        except configparser.Error as e:
            # The configuration file is optional. Any error causes the
            # theme to revert to the default state (but the error is
            # noted for theme debugging).
            self.errors['config'] = str(e)
            for key in theme_options:
                self.options[key.lower()] = None
            return
            
        for key in theme_options:
            try:
                self.options[key.lower()] = cfp.get('OPTIONS', key)
            except configparser.Error as e:
                # Problems with individual elements cause those elements
                # to be defaulted, and an error noted for the config               
                # file.
                self.options[key.lower()] = None
                self.errors['config'] = str(e)
                
            
    def load(self):
        """
        Load and compile templates.
        """
        pages = ['index', 'title', 'setup', 'chapter', 'sf', 'tsf', 'extra']
        templates = {}
        for page in pages:
            try:
              templates[page] = TAL.compileHTMLTemplate(self.source.load(page + '.html'))      
            except Exception as e:
              templates[page] = None
              self.errors[page] = str(e)
              
        self.indexpage = templates['index']
            
        self.titlepage = templates['title']
        self.setuppage = templates['setup']
        self.chapterpage = templates['chapter']

        self.sf_page = templates['sf']
        self.tst_page = templates['tsf']
        self.extrapage = templates['extra']
        
        return self.errors

        
def load_themes(theme_dir=THEME_DIR):
    """
    Scan the theme directory for templates and load them into the global 'themes' dict.
    """
    cwd = os.getcwd()
    os.chdir(theme_dir)
    for path in os.listdir('.'):
        t = Theme(path)
        themes[t.name] = t
